package com.sparrow.common.util;

import java.io.*;
import java.util.zip.*;

/**
 * 压缩,解压缩 工具类
 */
public class CompressUtil {

    /**
     * 压缩文件
     * @param sourceFilePath 源文件路径
     * @param compressedFilePath 压缩后文件的路径
     * @throws IOException 当文件操作出现异常时抛出
     */
    public static void compressFile(String sourceFilePath, String compressedFilePath) throws IOException {
        try (FileInputStream fileInputStream = new FileInputStream(sourceFilePath);
             FileOutputStream fileOutputStream = new FileOutputStream(compressedFilePath);
             GZIPOutputStream gzipOutputStream = new GZIPOutputStream(fileOutputStream)) {

            byte[] buffer = new byte[1024];
            int len;
            while ((len = fileInputStream.read(buffer)) != -1) {
                gzipOutputStream.write(buffer, 0, len);
            }
        }
    }


    /**
     * 解压缩文件
     * @param compressedFilePath 压缩文件的路径
     * @param targetFilePath 解压缩后文件的路径
     * @throws IOException 当文件操作出现异常时抛出
     */
    public static void decompressFile(String compressedFilePath, String targetFilePath) throws IOException {
        try (BufferedInputStream bis = new BufferedInputStream(new GZIPInputStream(new FileInputStream(compressedFilePath)));
             BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(targetFilePath))) {

            byte[] buffer = new byte[8192];
            int len;
            while ((len = bis.read(buffer)) != -1) {
                bos.write(buffer, 0, len);
            }
        }
    }

    /**
     * 压缩字节数组
     * @param input 待压缩的字节数组
     * @return 压缩后的字节数组
     * @throws IOException 当压缩过程中出现异常时抛出
     */
    public static byte[] compress(byte[] input) throws IOException {
        try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
             DeflaterOutputStream deflaterOutputStream = new DeflaterOutputStream(outputStream)) {
            deflaterOutputStream.write(input);
            deflaterOutputStream.finish();
            return outputStream.toByteArray();
        }
    }

    /**
     * 解压缩字节数组
     * @param input 待解压缩的字节数组
     * @return 解压缩后的字节数组
     * @throws IOException 当解压缩过程中出现异常时抛出
     */
    public static byte[] decompress(byte[] input) throws IOException {
        try (ByteArrayInputStream inputStream = new ByteArrayInputStream(input);
             InflaterInputStream inflaterInputStream = new InflaterInputStream(inputStream);
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {

            byte[] buffer = new byte[1024];
            int len;
            while ((len = inflaterInputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, len);
            }
            return outputStream.toByteArray();
        }
    }

    public static void zipDirectory(File dir, File zipFile) throws IOException {
        try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFile))) {
            zipFile(dir, dir.getName(), zos);
        }
    }

    private static void zipFile(File fileToZip, String fileName, ZipOutputStream zos) throws IOException {
        if (fileToZip.isHidden()) return;
        if (fileToZip.isDirectory()) {
            if (!fileName.endsWith("/")) fileName += "/";
            zos.putNextEntry(new ZipEntry(fileName));
            zos.closeEntry();
            for (File childFile : fileToZip.listFiles()) {
                zipFile(childFile, fileName + childFile.getName(), zos);
            }
            return;
        }
        try (FileInputStream fis = new FileInputStream(fileToZip)) {
            ZipEntry zipEntry = new ZipEntry(fileName);
            zos.putNextEntry(zipEntry);
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) != -1) {
                zos.write(buffer, 0, len);
            }
        }
    }

    public static void unzip(String zipFilePath, String destDir) throws IOException {
        File destDirectory = new File(destDir);
        if (!destDirectory.exists()) {
            destDirectory.mkdirs();
        }

        try (ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFilePath))) {
            ZipEntry entry;
            while ((entry = zipIn.getNextEntry()) != null) {
                String filePath = destDir + File.separator + entry.getName();
                if (entry.isDirectory()) {
                    File dir = new File(filePath);
                    if (!dir.exists()) dir.mkdirs();
                } else {
                    // 确保父目录存在
                    File parent = new File(filePath).getParentFile();
                    if (!parent.exists()) parent.mkdirs();

                    try (BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath))) {
                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = zipIn.read(buffer)) != -1) {
                            bos.write(buffer, 0, len);
                        }
                    }
                }
                zipIn.closeEntry();
            }
        }
    }

    public static void main(String[] args) {
        try {
            File dir = new File("D:\\Users\\Desktop\\temp");
            File zipFile = new File("D:\\Users\\Desktop\\back\\temp.zip");
            zipDirectory(dir, zipFile);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}